﻿/*
 * Erstellt mit SharpDevelop.
 * Benutzer: Kai Patrick
 * Datum: 17.03.2008
 * Zeit: 17:25
 * 
 * Sie können diese Vorlage unter Extras > Optionen > Codeerstellung > Standardheader ändern.
 */

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace Gamadus.Designer
{
	/// <summary>
	/// Description of ResourceMgr.
	/// </summary>
	public partial class ResourceMgr : Gamadus.Core.SingletonManager<ResourceMgr>
	{
		const int VERSION = 002;
		int nextID = 0;
		public string VersionString
		{
			get
			{
				return String.Format("{0:000}",VERSION).Insert(1,".");
			}
		}
		
		public bool VersionNewer(string v)
		{
			int i = int.Parse(v.Remove(1,1));
			return (i > VERSION);
		}
		
		public Dictionary<TreeNode, Resource> Resources = new Dictionary<TreeNode, Resource>();
		public Dictionary<ResourceType, TreeNode> TypeNodes = new Dictionary<ResourceType, TreeNode>();
		private Dictionary<ResourceType, Type> Types = new Dictionary<ResourceType, Type>();
		public List<IEditWindow> editWindows = new List<IEditWindow>();
		MainForm mainForm;
		public MainForm MainForm
		{
			get
			{
				return mainForm;
			}
		}
		
		string projectFile;
		string projectTitle;
		public string ProjectTitle
		{
			get
			{
				return projectTitle;
			}
		}
		
		bool didChanges;

		public bool DidChanges
		{
			get
			{
				return didChanges;
			}
			set
			{				
				didChanges = value;
				if(didChanges == true)
					MainForm.Text = "Gamadus Designer - "+projectTitle+"*";
				else
					MainForm.Text = "Gamadus Designer - "+projectTitle;
			}
		}
		
		string tempDir;
		public string TempDir
		{
			get
			{
				return tempDir;
			}
		}
		
		#region New, Close, Save, Open
		public void NewProject()
		{
			if(!CloseProject(true))
				return;
			
			projectTitle = "<new game>";
			DidChanges = false;
			projectFile = "";
			nextID = 0;
		}
		
		public bool CloseProject(bool checkEditWindows)
		{
			if(checkEditWindows)
			{
				while(editWindows.Count > 0)
				{
					IEditWindow window = editWindows[0];
					editWindows[0].Close();
					//find out if it has been closed
					if(editWindows.Count > 0 && editWindows[0] == window)
					{
						//it has not been closed
						return false;
					}
				}
			}
			
			
			if(DidChanges)
			{
				DialogResult result = MessageBox.Show("Games has been changed. Save changes?",
				                                      "Confirm", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
				if(result == DialogResult.Cancel)
					return false;
				if(result == DialogResult.Yes)
				{
					if(!SaveProject())
						return false;
				}
			}
			
			MainForm.CloseProject();
			
			return true;
		}
		
		public bool OpenProject()
		{
			if(!CloseProject(true))
				return false;
			
			OpenFileDialog dialog = new OpenFileDialog();
			dialog.AddExtension = true;
			dialog.DefaultExt = "gpf";
			if(dialog.ShowDialog() != DialogResult.OK)
				return false;
			
			return ResourceMgr.Instance.OpenProject(dialog.FileName);
		}
		
		public bool SaveProject()
		{
			if(projectFile == "")
				return SaveProjectAs();
			else
			{
				return SaveProject(projectFile);
			}
		}
		
		public bool SaveProjectAs()
		{
			SaveFileDialog dialog = new SaveFileDialog();
			dialog.AddExtension = true;
			dialog.DefaultExt = "gpf";
			if(dialog.ShowDialog() != DialogResult.OK)
				return false;
			dialog.Dispose();
			
			return SaveProject(dialog.FileName);
		}
		#endregion
		
		public void Init(MainForm mainForm)
		{
			char dirSep = System.IO.Path.DirectorySeparatorChar;
			string startPath = new System.IO.FileInfo(Application.StartupPath).FullName;
			tempDir = System.IO.Path.Combine(System.IO.Path.Combine(startPath, "Temp"),"Engine")+dirSep;
			if(!System.IO.Directory.Exists(tempDir))
				System.IO.Directory.CreateDirectory(tempDir);
			
			
			this.mainForm = mainForm;
			Types[ResourceType.Sprite] = typeof(Sprite);
			Types[ResourceType.Background] = typeof(Background);
			Types[ResourceType.Object] = typeof(Object);
			Types[ResourceType.Room] = typeof(Room);
			Types[ResourceType.Class] = typeof(ClassResource);
			
			NewProject();
		}
		
		public void Clean()
		{
			foreach(string f in System.IO.Directory.GetFiles(tempDir))
			{
				System.IO.File.Delete(f);
			}
			System.IO.Directory.Delete(tempDir);
		}
		
		public Resource Add(ResourceType type, bool showEditWindow)
		{
			return Add(type, showEditWindow, nextID++);
		}
		
		public Resource Add(ResourceType type, bool showEditWindow, int id)
		{
			Resource res = (Resource)System.Activator.CreateInstance(Types[type], id);
			
			TreeNode node = new TreeNode(res.Name);
			node.ImageKey = "none";
			node.SelectedImageKey = node.ImageKey;
			TypeNodes[type].Nodes.Add(node);
			Resources.Add(node, res);
			res.Node = node;
			
			int i = 0;
			string name;
			do
			{
				name = type.ToString().ToLower()+(i++);
			}
			while (!IsValidName(name));
			
			res.Name = name;
			
			if(showEditWindow)
			{
				TypeNodes[type].Expand();
				res.ShowEditWindow();
			}
			return res;
		}
		
		public Resource GetFirst(ResourceType type)
		{
			//TODO: handle subfolders
			foreach(TreeNode node in ResourceMgr.Instance.TypeNodes[type].Nodes)
			{
				if(ResourceMgr.Instance.Resources.ContainsKey(node))
				{
					return ResourceMgr.Instance.Resources[node];
				}
			}
			return null;
		}
		
		public Resource GetResourceByID(int id)
		{
			foreach(Resource res in Resources.Values)
			{
				if(res.ID == id)
					return res;
			}
			return null;
		}
			
		#region Validation functions and event handlers
		public bool ResourceNameExists(string name)
		{
			foreach(Resource res in Resources.Values)
			{
				if(res.Name == name)
					return true;
			}
			return false;
		}
		
		public bool ResourceNameExists(string name, Resource except)
		{
			foreach(Resource res in Resources.Values)
			{
				if(res.Name == name && res != except)
					return true;
			}
			return false;
		}
		
		
		public bool IsValidName(string name)
		{
			bool valid = (Regex.IsMatch(name,"^[_a-zA-Z]+[_a-zA-Z0-9]*$") && !ResourceNameExists(name));			
			return valid;
		}
		
		public bool IsValidName(string name, Resource res)
		{
			return (Regex.IsMatch(name,"^[_a-zA-Z]+[_a-zA-Z0-9]*$") && !ResourceNameExists(name, res));
		}
		
		public bool IsValidInteger(string name)
		{
			return Regex.IsMatch(name,"^[-]?[0-9]+$");
		}
		
		public bool IsValidPositiveInteger(string name)
		{
			return Regex.IsMatch(name,"^[1-9]+[0-9]*$");
		}
		
		public void ValidateResourceNameText(object sender, System.ComponentModel.CancelEventArgs e)
		{
			TextBox textBox = (sender as TextBox);
			object obj;
			IEditWindow window;
			obj = textBox.Parent;
			while(!(obj is IEditWindow))
			{
				obj = (obj as Control).Parent;
			}
			window = obj as IEditWindow;
			
			if(!IsValidName(textBox.Text,window.Editing))
			{
				
				textBox.BackColor = System.Drawing.Color.OrangeRed;
				e.Cancel = true;
			}
			else
			{
				textBox.BackColor = System.Drawing.Color.White;
				window.Editing.Node.Text = textBox.Text;
			}
		}
		
		public void ValidateIntegerText(object sender, System.ComponentModel.CancelEventArgs e)
		{
			if(sender is ToolStripTextBox)
			{
				ToolStripTextBox textBox = (sender as ToolStripTextBox);
				if(!IsValidInteger(textBox.Text))
				{
					textBox.BackColor = System.Drawing.Color.OrangeRed;
					e.Cancel = true;
				}
				else
				{
					textBox.BackColor = System.Drawing.Color.White;
				}
			}
			else
			{
				TextBox textBox = (sender as TextBox);
				if(!IsValidInteger(textBox.Text))
				{
					textBox.BackColor = System.Drawing.Color.OrangeRed;
					e.Cancel = true;
				}
				else
				{
					textBox.BackColor = System.Drawing.Color.White;
				}
			}
		}
		
		public void ValidatePositiveIntegerText(object sender, System.ComponentModel.CancelEventArgs e)
		{
			if(sender is ToolStripTextBox)
			{
				ToolStripTextBox textBox = (sender as ToolStripTextBox);
				if(!IsValidPositiveInteger(textBox.Text))
				{
					textBox.BackColor = System.Drawing.Color.OrangeRed;
					e.Cancel = true;
				}
				else
				{
					textBox.BackColor = System.Drawing.Color.White;
				}
			}
			else
			{
				TextBox textBox = (sender as TextBox);
				if(!IsValidPositiveInteger(textBox.Text))
				{
					textBox.BackColor = System.Drawing.Color.OrangeRed;
					e.Cancel = true;
				}
				else
				{
					textBox.BackColor = System.Drawing.Color.White;
				}
			}
		}
		#endregion
	}
}
